package com.gdut.wifidemo.strategy.impl;

import android.os.Handler;
import android.os.Looper;

import com.gdut.wifidemo.common.RequestCallback;
import com.gdut.wifidemo.data.entity.Result;
import com.gdut.wifidemo.data.entity.Wifi;
import com.gdut.wifidemo.strategy.IStrategy;
import com.gdut.wifidemo.utils.LogUtils;

import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;

public class KnnStrategy implements IStrategy {

    private Comparator<Wifi> comparator = new Comparator<Wifi>() {
        @Override
        public int compare(Wifi o1, Wifi o2) {
            if (o1.getRssi() >= o2.getRssi()) {
                return 1;
            }
            return 0;
        }
    };

    @Override
    public void calculate(final List<Wifi> testData, final RequestCallback<Result> callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                final Result result = knn(testData);
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        if (result == null) {
                            if (callback != null) {
                                callback.onFailure("System Error");
                            }
                        } else {
                            if (callback != null) {
                                callback.onSuccess(result);
                            }
                        }
                    }
                });
            }
        }).start();
    }

    private Result knn(List<Wifi> testData) {
        if (testData == null || testData.size() == 0) {
            LogUtils.e("testData == null or testData.size == 0");
            return null;
        }
        LogUtils.d(testData.toString());
        int k = (testData.size() % 5) + 1;  // +1 for avoid IllegalArgumentException
        PriorityQueue<Wifi> priorityQueue = new PriorityQueue<>(k, comparator);
        for (int i = 0; i < k; i++) {
            priorityQueue.add(testData.get(i));
        }
        return getMostClass(priorityQueue);
    }

    private Result getMostClass(PriorityQueue<Wifi> priorityQueue) {
        if (priorityQueue == null || priorityQueue.isEmpty()) {
            return null;
        }
        Map<String, Integer> map = new HashMap<>();
        for (int i = 0; i < priorityQueue.size(); i++) {
            Wifi wifi = priorityQueue.remove();
            String key = wifi.getSsid();
            if (map.containsKey(key)) {
                map.put(key, map.get(key) + 1);
            } else {
                map.put(key, 1);
            }
        }
        Result result = new Result();
        int maxIndex = -1;
        int maxCount = 0;
        Object[] keys = map.keySet().toArray();
        for (int i = 0; i < keys.length; i++) {
            if (map.get(keys[i].toString()) > maxCount) {
                maxCount = map.get(keys[i].toString());
                maxIndex = i;
            }
        }
        result.setPosition(keys[maxIndex].toString());
        return result;
    }
}
